
#include "spi_flash.h"

#include <stdio.h>
#include "stdbool.h"
#include "board_config.h"
#include "nrf_gpio.h"
#include "app_scheduler.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_spi.h"
#include "sdk_common.h"
#include "app_util_platform.h"
#include "nrf_delay.h"

#if USE_VBUS
#include "vbus.h"
#include "vbus_evt.h"
#endif

volatile uint32_t spi_id =0;
uint8_t spi_flash_write_flag    = 0;
uint8_t spim_buffer[266]        = {0};
uint8_t spim_rxbuf[260]         = {0};
nrf_drv_spi_t spi_flash_add     = NRF_DRV_SPI_INSTANCE(SPI_FLASH_BASE_ADDRESS);

#define SPI_FLASH_CS_LOW()       nrf_gpio_pin_clear(SPI_FLASH_CS_PIN)
#define SPI_FLASH_CS_HIGH()      nrf_gpio_pin_set(SPI_FLASH_CS_PIN)


/* Private typedef -----------------------------------------------------------*/
//#define SPI_FLASH_PageSize      4096
#define SPI_FLASH_PageSize      4096
#define SPI_FLASH_PerWritePageSize      256
#define SPI_FLASH_BlockSize             65536

/* Private define ------------------------------------------------------------*/
#define W25X_WriteEnable		      0x06 
#define W25X_WriteDisable		      0x04 
#define W25X_ReadStatusReg		    0x05 
#define W25X_WriteStatusReg		    0x01 
#define W25X_ReadData			      	0x03 
#define W25X_FastReadData		      0x0B 
#define W25X_FastReadDual		      0x3B 
#define W25X_PageProgram		      0x02 
#define W25X_BlockErase			      0xD8 
#define W25X_SectorErase		      0x20 
#define W25X_ChipErase			      0xC7 
#define W25X_PowerDown			      0xB9 
#define W25X_ReleasePowerDown	    0xAB 
#define W25X_DeviceID			      	0xAB 
#define W25X_ManufactDeviceID   	0x90 
#define W25X_JedecDeviceID		    0x9F 

#define WIP_Flag                  0x01  /* Write In Progress (WIP) flag */

#define Dummy_Byte                0xFF

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);                /**< SPI instance. */


void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SPI_EVENT_DONE)
    {
        nrf_gpio_pin_set(SPI_FLASH_CS_PIN);
        spi_flash_write_flag = true; 
    }
}

/*******************************************************************************
* Function Name  : spi_flash_init
* Description    : Initializes the hardware SPI FLASH 
* Input          : None
* Output         : None
* Return         : err_code
*******************************************************************************/
uint32_t spi_flash_init(void)
{
    nrf_gpio_cfg_output(SPI_FLASH_CS_PIN);    
    uint32_t err_code;
    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG(0);
    spi_config.frequency = NRF_DRV_SPI_FREQ_4M;
//    spi_config.frequency = NRF_DRV_SPI_FREQ_125K;
    spi_config.ss_pin = IO_NOT_USE;
    err_code = nrf_drv_spi_init(&spi, &spi_config, spi_event_handler);
    nrf_gpio_pins_set(SPI_FLASH_CS_PIN);
    return err_code;
}

/*******************************************************************************
* Function Name  : spi_flash_uninit
* Description    : uninitializes the hardware SPI FLASH 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void spi_flash_uninit(void)
{
    nrf_drv_spi_uninit(&spi);
    nrf_gpio_pins_set(SPI_FLASH_CS_PIN);
}

/*******************************************************************************
* Function Name  : spim_init
* Description    : Initializes the hardware SPI FLASH 
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void spim_init(void)
{
    uint32_t err_code;
       
    err_code = spi_flash_init();
    APP_ERROR_CHECK(err_code);
    nrf_gpio_cfg_output(SPI_FLASH_CS_PIN);
    nrf_gpio_pins_set(SPI_FLASH_CS_PIN);
}


/*******************************************************************************
* Function Name  : SPI_FLASH_Init
* Description    : Initializes the peripherals used by the SPI FLASH driver.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_Init(void)
{

    uint32_t err;

    nrf_gpio_cfg_output(SPI_FLASH_CS_PIN);
    SPI_FLASH_CS_HIGH();

}
/*******************************************************************************
* Function Name  : SPI_FLASH_SectorErase
* Description    : Erases the specified FLASH sector.
* Input          : SectorAddr: address of the sector to erase.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_SectorErase(uint32_t SectorAddr)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable();
  SPI_FLASH_WaitForWriteEnd();
  /* Sector Erase */
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
  /* Send Sector Erase instruction */
  SPI_FLASH_SendByte(W25X_SectorErase);
  /* Send SectorAddr high nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
  /* Send SectorAddr medium nibble address byte */
  SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
  /* Send SectorAddr low nibble address byte */
  SPI_FLASH_SendByte(SectorAddr & 0xFF);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BulkErase
* Description    : Erases the entire FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BulkErase(void)
{
  /* Send write enable instruction */
  SPI_FLASH_WriteEnable();

  /* Bulk Erase */
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();
  /* Send Bulk Erase instruction  */
  SPI_FLASH_SendByte(W25X_ChipErase);
  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();

  /* Wait the end of Flash writing */
  SPI_FLASH_WaitForWriteEnd();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_PageWrite
* Description    : Writes more than one byte to the FLASH with a single WRITE
*                  cycle(Page WRITE sequence). The number of byte can't exceed
*                  the FLASH page size.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH,
*                    must be equal or less than "SPI_FLASH_PageSize" value.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite,uint8_t offset)
{
    uint32_t err;
    uint32_t add;
    add = WriteAddr * SPI_FLASH_PerWritePageSize + offset;
    
    SPI_FLASH_WriteEnable();
     /* Chip Select high */
    SPI_FLASH_CS_HIGH();
//    spim_dma_buffer[0] = W25X_WriteEnable;                  // Enable the write access to the FLASH 
    spim_buffer[0] = W25X_PageProgram;                  // Page Program Command
    spim_buffer[1] = (add & 0xFF0000) >> 16;      // Add bit23~bit16
    spim_buffer[2] = (add & 0x00FF00) >> 8;       // Add bit15~bit8
    spim_buffer[3] = (add & 0x0000FF) >> 0;       // Add bit7~bit0
    
    for(uint16_t i=0;i<NumByteToWrite;i++)
    {
        spim_buffer[4+i] = pBuffer[i];
    }
    
//    err = spi_flash_init();
//    APP_ERROR_CHECK(err);
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW();
    err = nrf_drv_spi_transfer(&spi,spim_buffer,NumByteToWrite + 4,NULL,0);    
    APP_ERROR_CHECK(err);
//    while(!spi_flash_write_flag);
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    spi_flash_uninit();
    
}

/*******************************************************************************
* Function Name  : SPI_FLASH_PageRead
* Description    : Read a page to the FLASH with a single Read
*                  cycle(Page Read sequence). The number of byte can't exceed
*                  a FLASH page size.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    Read from the FLASH.
*                  - ReadAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to read from the FLASH,
*                    must be equal or less than "SPI_FLASH_PageSize" value.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_PageRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead, uint8_t offset)
{
    uint32_t err;
    uint32_t add;
    add = ReadAddr * SPI_FLASH_PerWritePageSize + offset;
     /* Chip Select high */
//    SPI_FLASH_CS_HIGH();
    spim_buffer[0] = W25X_ReadData;               // Read Data Bytes Command
    spim_buffer[1] = (add & 0xFF0000) >> 16;      // Add bit23~bit16
    spim_buffer[2] = (add & 0x00FF00) >> 8;       // Add bit15~bit8
    spim_buffer[3] = (add & 0x0000FF) >> 0;       // Add bit7~bit0
    
    err = spi_flash_init();
    APP_ERROR_CHECK(err);
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW();
    spi_flash_write_flag = false;
    err = nrf_drv_spi_transfer(&spi,spim_buffer,4,pBuffer,NumByteToRead + 4 );    
//    while(!spi_flash_write_flag);
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    APP_ERROR_CHECK(err);
    spi_flash_uninit();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_BufferWrite
* Description    : Writes block of data to the FLASH. In this function, the
*                  number of WRITE cycles are reduced, using Page WRITE sequence.
* Input          : - pBuffer : pointer to the buffer  containing the data to be
*                    written to the FLASH.
*                  - WriteAddr : FLASH's internal address to write to.
*                  - NumByteToWrite : number of bytes to write to the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
/*
void SPI_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
  uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

	SPI_FLASH_Init();
	
  Addr = WriteAddr % SPI_FLASH_PageSize;
  count = SPI_FLASH_PageSize - Addr;
  NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
  NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

  if (Addr == 0) //WriteAddr is SPI_FLASH_PageSize aligned  
  {
    if (NumOfPage == 0) // NumByteToWrite < SPI_FLASH_PageSize 
    {
      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
    }
    else // NumByteToWrite > SPI_FLASH_PageSize 
    {
      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
    }
  }
  else // WriteAddr is not SPI_FLASH_PageSize aligned  
  {
    if (NumOfPage == 0) // NumByteToWrite < SPI_FLASH_PageSize
    {
      if (NumOfSingle > count) // (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize 
      {
        temp = NumOfSingle - count;

        SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
        WriteAddr +=  count;
        pBuffer += count;

        SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
      }
      else
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
      }
    }
    else // NumByteToWrite > SPI_FLASH_PageSize 
    {
      NumByteToWrite -= count;
      NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
      NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;

      SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
      WriteAddr +=  count;
      pBuffer += count;

      while (NumOfPage--)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
        WriteAddr +=  SPI_FLASH_PageSize;
        pBuffer += SPI_FLASH_PageSize;
      }

      if (NumOfSingle != 0)
      {
        SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
      }
    }
  }
}
*/

/*******************************************************************************
* Function Name  : SPI_FLASH_BufferRead
* Description    : Reads a block of data from the FLASH.
* Input          : - pBuffer : pointer to the buffer that receives the data read
*                    from the FLASH.
*                  - ReadAddr : FLASH's internal address to read from.
*                  - NumByteToRead : number of bytes to read from the FLASH.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
//  SPI_FLASH_Init();
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();

  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(W25X_ReadData);

  /* Send ReadAddr high nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  /* Send ReadAddr medium nibble address byte to read from */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  /* Send ReadAddr low nibble address byte to read from */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);

  while (NumByteToRead--) /* while there is data to be read */
  {
    /* Read a byte from the FLASH */
    *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);
    /* Point to the next location where the byte read will be saved */
    pBuffer++;
  }

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
	
//	 spi_master_disable(SPI_FLASH_BASE_ADDRESS);

}

void SPI_FLASH_Read_Sector(uint32_t nSector, uint8_t* pBuffer,uint16_t length)
{
	uint16_t i;
	
	nSector *= SPI_FLASH_PageSize;
	
	SPI_FLASH_CS_LOW();
	SPI_FLASH_SendByte(W25X_ReadData);
	SPI_FLASH_SendByte((uint8_t)(nSector >> 16));
	SPI_FLASH_SendByte((uint8_t)(nSector>> 8));
	SPI_FLASH_SendByte((uint8_t) nSector);
	
	for(i = 0;i< length;i++)
	{
		pBuffer[i] =  SPI_FLASH_SendByte(Dummy_Byte);
	}
	SPI_FLASH_CS_HIGH();
	SPI_FLASH_WaitForWriteEnd();
}

void SPI_FLASH_Read_Sector_Ex(uint32_t nSector, uint8_t* pBuffer,uint16_t length,uint16_t offset)
{
    uint16_t i;
    uint32_t addr;
    addr = nSector * SPI_FLASH_PageSize;
    addr += offset;
    SPI_FLASH_BufferRead(pBuffer,addr,length);
}

void SPI_FLASH_Erase_Sector(uint32_t nDest)
{
    uint32_t err;
    //NRF_LOG_PRINTF("SPI_FLASH_Erase_Sector nDest = %d",nDest);
    nDest *= SPI_FLASH_PageSize;

    SPI_FLASH_WriteEnable();
    /* Chip Select high */
    SPI_FLASH_CS_HIGH();
    spim_buffer[0] = W25X_SectorErase;
    // 先暂时改为擦除块
//    spim_buffer[0] = W25X_BlockErase;
    spim_buffer[1] = (uint8_t)((nDest & 0xFFFFFF) >> 16);
    spim_buffer[2] = (uint8_t)((nDest & 0xFFFF) >> 8);
    spim_buffer[3] = (uint8_t)nDest & 0xFF;
    
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW();
    err = nrf_drv_spi_transfer(&spi,spim_buffer,4,NULL,0);    
    APP_ERROR_CHECK(err);
//    while(!spi_flash_write_flag);
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    spi_flash_uninit();
}

void SPI_FLASH_Erase_Block(uint32_t nDest)
{
    uint32_t err;
    //NRF_LOG_PRINTF("SPI_FLASH_Erase_Sector nDest = %d",nDest);
    nDest *= SPI_FLASH_BlockSize;

    SPI_FLASH_WriteEnable();
    /* Chip Select high */
    SPI_FLASH_CS_HIGH();
    spim_buffer[0] = W25X_BlockErase;
    spim_buffer[1] = (uint8_t)((nDest & 0xFFFFFF) >> 16);
    spim_buffer[2] = (uint8_t)((nDest & 0xFFFF) >> 8);
    spim_buffer[3] = (uint8_t)nDest & 0xFF;
    
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW();
    err = nrf_drv_spi_transfer(&spi,spim_buffer,4,NULL,0);    
    APP_ERROR_CHECK(err);
//    while(!spi_flash_write_flag);
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    spi_flash_uninit();
}


void SPI_FLASH_Write_Sector(uint32_t nSector, uint8_t* pBuffer,uint16_t length)
{	
	int i,j;
	
	nSector *= SPI_FLASH_PageSize;
	for(j=0;j < length/SPI_FLASH_PerWritePageSize;j++)
	{
		SPI_FLASH_WriteEnable();
		SPI_FLASH_CS_LOW();
		
		SPI_FLASH_SendByte(W25X_PageProgram);
		SPI_FLASH_SendByte((uint8_t)(nSector >> 16));
		SPI_FLASH_SendByte((uint8_t)(nSector >> 8));	
		SPI_FLASH_SendByte((uint8_t) nSector);
		
		for(i=0;i<SPI_FLASH_PerWritePageSize;i++)								
			SPI_FLASH_SendByte(pBuffer[i]);
		
		pBuffer += SPI_FLASH_PerWritePageSize;
		nSector += SPI_FLASH_PerWritePageSize;

		SPI_FLASH_CS_HIGH();
		SPI_FLASH_WaitForWriteEnd();
	}
}

void SPI_FLASH_Write_Sector_Ex(uint32_t nSector, uint8_t* pBuffer,uint16_t length,uint16_t offset)
{
    uint32_t addr;
    int j,i;
    addr = nSector * SPI_FLASH_PageSize;
    addr += offset;
    for(j=0;j < length/SPI_FLASH_PerWritePageSize;j++)
    {
        SPI_FLASH_WriteEnable();
        SPI_FLASH_CS_LOW();
        
        SPI_FLASH_SendByte(W25X_PageProgram);
        SPI_FLASH_SendByte((uint8_t)(addr >> 16));
        SPI_FLASH_SendByte((uint8_t)(addr >> 8));	
        SPI_FLASH_SendByte((uint8_t) addr);
        
        for(i=0;i<SPI_FLASH_PerWritePageSize;i++)								
            SPI_FLASH_SendByte(pBuffer[i]);
        
        pBuffer += SPI_FLASH_PerWritePageSize;
        addr += SPI_FLASH_PerWritePageSize;

        SPI_FLASH_CS_HIGH();
        SPI_FLASH_WaitForWriteEnd();
    }
}



/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
uint32_t SPI_FLASH_ReadID(void)
{
  uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
  

	SPI_FLASH_Init();
  /* Select the FLASH: Chip Select low */
	SPI_FLASH_CS_LOW();
  /* Send "RDID " instruction */
  SPI_FLASH_SendByte(W25X_JedecDeviceID);

  /* Read a byte from the FLASH */
  Temp0 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Read a byte from the FLASH */
  Temp1 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Read a byte from the FLASH */
  Temp2 = SPI_FLASH_SendByte(Dummy_Byte);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();

  Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

//	 nrf_drv_spi_uninit(&flash_spi);

  return Temp;
}

//#if USE_VBUS
//static uint32_t flash_vbus_control(uint32_t cmd,void *data,uint32_t size)
//{
//    switch(cmd)
//    {
//        case VBUS_EVT_DTM_FLASH_IC :
//        {
//            uint8_t spi_flash_status=0;
//            if(spi_id == 19)
//            {
//                spi_flash_status =0;   //通信成功
//            }else{
//                spi_flash_status =1;   //通信失败
//            }
//            vbus_tx_data(VBUS_EVT_DTM_FLASH_IC_SEND, &spi_flash_status, sizeof(uint8_t));    
//        }
//        break;
//    }
//    return 0;
//}

//static void flash_vbus_init()
//{
//    uint32_t err;
//    struct vbus_t vbus;
//    uint32_t id;
//    memset(&vbus,0,sizeof(vbus));
//    vbus.control = flash_vbus_control;
//    vbus.name = "flash";
//    err = vbus_reg(vbus,&id);
//    APP_ERROR_CHECK(err);
//}
//#endif

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadID
* Description    : Reads FLASH identification.
* Input          : None
* Output         : None
* Return         : FLASH identification
*******************************************************************************/
uint32_t SPI_FLASH_ReadDeviceID(void)
{
    uint8_t read_id = 0;
    uint32_t Temp = 0;
    uint32_t err_code;
    //SPI_FLASH_Init();
    
    SPI_FLASH_CS_HIGH();
    
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW();
    
    spim_buffer[0] = W25X_DeviceID;
    spim_buffer[1] = Dummy_Byte;
    spim_buffer[2] = Dummy_Byte;
    spim_buffer[3] = Dummy_Byte;
    
    err_code = nrf_drv_spi_transfer(&spi,spim_buffer,4,spim_rxbuf,6);    
    APP_ERROR_CHECK(err_code);

//    while(!spi_flash_write_flag);
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    read_id = spim_rxbuf[4];
    Temp = (uint32_t) read_id;
//    Temp = *(uint32_t *) (spim_rxbuf);

    /* Deselect the FLASH: Chip Select high */
//    SPI_FLASH_CS_HIGH();

    return Temp;
}
/*******************************************************************************
* Function Name  : SPI_FLASH_StartReadSequence
* Description    : Initiates a read data byte (READ) sequence from the Flash.
*                  This is done by driving the /CS line low to select the device,
*                  then the READ instruction is transmitted followed by 3 bytes
*                  address. This function exit and keep the /CS line low, so the
*                  Flash still being selected. With this technique the whole
*                  content of the Flash is read with a single READ instruction.
* Input          : - ReadAddr : FLASH's internal address to read from.
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_StartReadSequence(uint32_t ReadAddr)
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();

  /* Send "Read from Memory " instruction */
  SPI_FLASH_SendByte(W25X_ReadData);

  /* Send the 24-bit address of the address to read from -----------------------*/
  /* Send ReadAddr high nibble address byte */
  SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
  /* Send ReadAddr medium nibble address byte */
  SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);
  /* Send ReadAddr low nibble address byte */
  SPI_FLASH_SendByte(ReadAddr & 0xFF);
}

/*******************************************************************************
* Function Name  : SPI_FLASH_ReadByte
* Description    : Reads a byte from the SPI Flash.
*                  This function must be used only if the Start_Read_Sequence
*                  function has been previously called.
* Input          : None
* Output         : None
* Return         : Byte Read from the SPI Flash.
*******************************************************************************/
uint8_t SPI_FLASH_ReadByte(void)
{
  return (SPI_FLASH_SendByte(Dummy_Byte));
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendByte
* Description    : Sends a byte through the SPI interface and return the byte
*                  received from the SPI bus.
* Input          : byte : byte to send.
* Output         : None
* Return         : The value of the received byte.
*******************************************************************************/
uint8_t SPI_FLASH_SendByte(uint8_t byte)
{
    uint8_t tx_buf[1];
    uint8_t rx_buf[1];
    uint32_t err;
    tx_buf[0] = byte;
    err =nrf_drv_spi_transfer(&spi_flash_add, tx_buf, sizeof(tx_buf), rx_buf,sizeof(rx_buf));
    APP_ERROR_CHECK(err);
//    err =nrf_drv_spi_transfer(&gsensor_spi, tx_buf, sizeof(tx_buf), rx_buf,sizeof(rx_buf));
//    APP_ERROR_CHECK(err);
//    err = spi_master_send_recv(SPI_FLASH_BASE_ADDRESS,tx_buf,sizeof(tx_buf),rx_buf,sizeof(rx_buf));
//    APP_ERROR_CHECK(err);
    return rx_buf[0];
}

/*******************************************************************************
* Function Name  : SPI_FLASH_SendHalfWord
* Description    : Sends a Half Word through the SPI interface and return the
*                  Half Word received from the SPI bus.
* Input          : Half Word : Half Word to send.
* Output         : None
* Return         : The value of the received Half Word.
*******************************************************************************/
uint16_t SPI_FLASH_SendHalfWord(uint16_t HalfWord)
{
  /* Loop while DR register in not emplty */
//  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

//  /* Send Half Word through the SPI1 peripheral */
//  SPI_I2S_SendData(SPI1, HalfWord);

//  /* Wait to receive a Half Word */
//  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

//  /* Return the Half Word read from the SPI bus */
//  return SPI_I2S_ReceiveData(SPI1);
    return 0;
}

/*******************************************************************************
* Function Name  : SPI_FLASH_WriteEnable
* Description    : Enables the write access to the FLASH.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WriteEnable(void)
{
    uint32_t err;
    uint8_t tx_buf[1];
    uint8_t rx_buf[1];
    // initial hardware spi for flash
    spi_flash_init();
    /* Select the FLASH: Chip Select low */
    SPI_FLASH_CS_LOW(); 
    /* Send "Write Enable" instruction */
    tx_buf[0] = W25X_WriteEnable;
    spi_flash_write_flag = false;
    err = nrf_drv_spi_transfer(&spi,tx_buf,sizeof(tx_buf),NULL,0);        
//    while(!spi_flash_write_flag);    
    for(uint8_t i=0;i<250;i++)
    {
        if(spi_flash_write_flag)
        {
            spi_flash_write_flag = false;
            i = 251;
        }
    }
    spi_flash_write_flag = false;
    APP_ERROR_CHECK(err);
//    nrf_delay_ms(1);
//    spi_flash_uninit();
}

/*******************************************************************************
* Function Name  : SPI_FLASH_WaitForWriteEnd
* Description    : Polls the status of the Write In Progress (WIP) flag in the
*                  FLASH's status  register  and  loop  until write  opertaion
*                  has completed.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_FLASH_WaitForWriteEnd(void)
{
  uint8_t FLASH_Status = 0;

  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();

  /* Send "Read Status Register" instruction */
  SPI_FLASH_SendByte(W25X_ReadStatusReg);

  /* Loop as long as the memory is busy with a write cycle */
  do
  {
    /* Send a dummy byte to generate the clock needed by the FLASH
    and put the value of the status register in FLASH_Status variable */
    FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);	 
  }
  while ((FLASH_Status & WIP_Flag) != 0); /* Write in progress */
  //while ((FLASH_Status & WIP_Flag) == SET); /* Write in progress */

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
}


//进入掉电模式
void SPI_Flash_PowerDown(void)   
{ 
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();

  /* Send "Power Down" instruction */
  SPI_FLASH_SendByte(W25X_PowerDown);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();
}   

//唤醒
void SPI_Flash_WAKEUP(void)   
{
  /* Select the FLASH: Chip Select low */
  SPI_FLASH_CS_LOW();

  /* Send "Power Down" instruction */
  SPI_FLASH_SendByte(W25X_ReleasePowerDown);

  /* Deselect the FLASH: Chip Select high */
  SPI_FLASH_CS_HIGH();                   //等待TRES1
}   
   


int spi_flash_read(uint32_t addr, uint8_t *data, uint32_t len)
{
	    uint32_t err=0;
			SPI_FLASH_Init();
  
     SPI_Flash_WAKEUP();
  
  
		 SPI_FLASH_BufferRead( data, addr, len);
  
     SPI_Flash_PowerDown();
  
//		 nrf_drv_spi_uninit(&flash_spi);

		 return 0;	
}
/*********************************************END OF FILE**********************/
